<!DOCTYPE html>
<html lang=zh>
<head>
    <meta charset="utf-8">
    
    <title>程序猿</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
    <meta property="og:type" content="website">
<meta property="og:title" content="程序猿">
<meta property="og:url" content="http://yoursite.com/index.html">
<meta property="og:site_name" content="程序猿">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="程序猿">
    

    
        <link rel="alternate" href="/" title="程序猿" type="application/atom+xml" />
    

    

    <link rel="stylesheet" href="/libs/font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="/libs/open-sans/styles.css">
    <link rel="stylesheet" href="/libs/source-code-pro/styles.css">

    <link rel="stylesheet" href="/css/style.css">

    <script src="/libs/jquery/2.1.3/jquery.min.js"></script>
    
    
        <link rel="stylesheet" href="/libs/lightgallery/css/lightgallery.min.css">
    
    
        <link rel="stylesheet" href="/libs/justified-gallery/justifiedGallery.min.css">
    
    
    
    


</head>

<body>
    <div id="container">
        <header id="header">
    <div id="header-main" class="header-inner">
        <div class="outer">
            <a href="/" id="logo">
                <i class="logo"></i>
                <span class="site-title">程序猿</span>
            </a>
            <nav id="main-nav">
                
                    <a class="main-nav-link" href="http://chinesszz.oschina.io/">主页</a>
                
                    <a class="main-nav-link" href="/archives">档案</a>
                
                    <a class="main-nav-link" href="/archives">分类</a>
                
                    <a class="main-nav-link" href="/archives">标签</a>
                
                    <a class="main-nav-link" href="/关于我">关于我</a>
                
            </nav>
            
                
                <nav id="sub-nav">
                    <div class="profile" id="profile-nav">
                        <a id="profile-anchor" href="javascript:;">
                            <img class="avatar" src="/css/images/avatar.png" />
                            <i class="fa fa-caret-down"></i>
                        </a>
                    </div>
                </nav>
            
            <div id="search-form-wrap">

    <form class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
        <button type="submit" class="search-form-submit"></button>
    </form>
    <div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="想要查找什么..." />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

</div>
        </div>
    </div>
    <div id="main-nav-mobile" class="header-sub header-inner">
        <table class="menu outer">
            <tr>
                
                    <td><a class="main-nav-link" href="http://chinesszz.oschina.io/">主页</a></td>
                
                    <td><a class="main-nav-link" href="/archives">档案</a></td>
                
                    <td><a class="main-nav-link" href="/archives">分类</a></td>
                
                    <td><a class="main-nav-link" href="/archives">标签</a></td>
                
                    <td><a class="main-nav-link" href="/关于我">关于我</a></td>
                
                <td>
                    
    <div class="search-form">
        <input type="text" class="ins-search-input search-form-input" placeholder="搜索" />
    </div>

                </td>
            </tr>
        </table>
    </div>
</header>

        <div class="outer">
            
                

<aside id="profile">
    <div class="inner profile-inner">
        <div class="base-info profile-block">
            <img id="avatar" src="/css/images/avatar.png" />
            <h2 id="name">刘鑫</h2>
            <h3 id="title">一个热爱生活喜欢技术的程序猿</h3>
            <span id="location"><i class="fa fa-map-marker"></i>shanghai, China</span>
            <a id="follow" target="_blank" href="https://github.com/lxchinesszz">关注我</a>
        </div>
        <div class="article-info profile-block">
            <div class="article-info-block">
                25
                <span>文章</span>
            </div>
            <div class="article-info-block">
                19
                <span>标签</span>
            </div>
        </div>
        
        <div class="profile-block social-links">
            <table>
                <tr>
                    
                    
                    <td>
                        <a href="https://github.com/lxchinesszz" target="_blank" title="github" class=tooltip>
                            <i class="fa fa-github"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="twitter" class=tooltip>
                            <i class="fa fa-twitter"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="facebook" class=tooltip>
                            <i class="fa fa-facebook"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="dribbble" class=tooltip>
                            <i class="fa fa-dribbble"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="http://weibo.com/u/5513970927?is_all=1" target="_blank" title="weibo" class=tooltip>
                            <i class="fa fa-weibo"></i>
                        </a>
                    </td>
                    
                    <td>
                        <a href="/" target="_blank" title="rss" class=tooltip>
                            <i class="fa fa-rss"></i>
                        </a>
                    </td>
                    
                </tr>
            </table>
        </div>
        
    </div>
</aside>

            
            <section id="main">
    <article id="Layout-CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/">CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/">
            <time datetime="2017-05-16T16:00:00.000Z" itemprop="datePublished">2017-05-17</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/服务器/">服务器</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/计算/">计算</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h3 id="CPU-bound-计算密集型-和IO-bound-IO密集型"><a href="#CPU-bound-计算密集型-和IO-bound-IO密集型" class="headerlink" title="CPU-bound(计算密集型) 和IO bound(IO密集型)"></a>CPU-bound(计算密集型) 和IO bound(IO密集型)</h3><blockquote>
<p>I/O bound指的是系统CPU效能相对硬盘和内存好很多，此时大部分CPU在等io的读写，此时CPU Loading不高。</p>
<p>CPU bound指的是系统的硬盘和内存的性能，相对于CPU的性能要好很多，此时系统运作CPU Loading 100% ，CPU要读写，I/O在很短时间完成，而CPU还有很多运算要处理，CPU Loading很高。</p>
</blockquote>
<ul>
<li>大部分时间用来做计算和逻辑判断等CPU动作的程序称之为CPU bound。例如计算圆周率，在执行过程中绝大部分时间用在三角函数和开根号的计算，便是CPU bound程序</li>
</ul>
<blockquote>
<p>CPU bound的程序一般而言CPU占用率相当高。这可能是因为任务本身不太需要访问I/O设备，也可能是因为程序是多线程实现因此屏蔽掉了等待I/O的时间。<br>而I/O bound的程序一般在达到性能极限时，CPU占用率仍然较低。这可能是因为任务本身需要大量I/O操作，而pipeline(管道通信)做得不是很好，没有充分利用处理器能力<br>；还可能是因为数据局部性不是很好，导致较多page error,结果产生了大量disk I/O的开销。</p>
</blockquote>
<p>==如何分辨到底是CPU还是IO bound？==</p>
<h3 id="进程vs线程"><a href="#进程vs线程" class="headerlink" title="进程vs线程"></a>进程vs线程</h3><ul>
<li>如果用多进程实现Master-Worker，主进程就是Master，其他进程就是Worker。</li>
<li><p>如果用多线程实现Master-Worker，主线程就是Master，其他线程就是Worker。</p>
<ul>
<li><p>多进程优缺点</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">多进程模式最大的优点就是稳定性高，因为一个子进程崩溃了，不会影响主进程和其他子进程。当然主进程挂了所有进程就全挂了，但是Master进程只负责分配任务，挂掉的概率低）著名的Apache最早就是采用多进程模式。多进程模式的缺点是创建进程的代价大，在Unix/Linux系统下，用fork调用还行，在Windows下创建进程开销巨大。另外，操作系统能同时运行的进程数也是有限的，在内存和CPU的限制下，如果有几千个进程同时运行，操作系统连调度都会成问题。</div></pre></td></tr></table></figure>
</li>
<li><p>多线程优缺点</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">多线程模式通常比多进程快一点，但是也快不到哪去，而且，多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃，因为所有线程共享进程的内存。在Windows上，如果一个线程执行的代码出了问题，你经常可以看到这样的提示：“该程序执行了非法操作，即将关闭”，其实往往是某个线程出了问题，但是操作系统会强制结束整个进程。</div><div class="line">在Windows下，多线程的效率比多进程要高，所以微软的IIS服务器默认采用多线程模式。由于多线程存在稳定性的问题，IIS的稳定性就不如Apache。为了缓解这个问题，IIS和Apache现在又有多进程+多线程的混合模式，真是把问题越搞越复杂。</div></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/" data-id="cizk115au0000jj8z43i1ni28" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Boot中使用@Async实现异步调用" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2017/04/27/Spring Boot中使用@Async实现异步调用/">Spring Boot中使用@Async实现异步调用</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2017/04/27/Spring Boot中使用@Async实现异步调用/">
            <time datetime="2017-04-26T16:00:00.000Z" itemprop="datePublished">2017-04-27</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Boot实战/">Spring Boot实战</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Boot中使用-Async实现异步调用/">Spring Boot中使用@Async实现异步调用</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>本文引用地址大神程序员DD  <a href="http://blog.didispace.com/springbootasyncs" target="_blank" rel="external">link</a> </p>
</blockquote>
<p>什么是“异步调用”？</p>
<p>“异步调用”对应的是“同步调用”，同步调用指程序按照定义顺序依次执行，每一行程序都必须等待上一行程序执行完成之后才能执行；异步调用指程序在顺序执行时，不等待异步调用的语句返回结果就执行后面的程序。</p>
<h3 id="同步调用"><a href="#同步调用" class="headerlink" title="同步调用"></a>同步调用</h3><p>下面通过一个简单示例来直观的理解什么是同步调用：</p>
<ul>
<li>定义Task类，创建三个处理函数分别模拟三个执行任务的操作，操作消耗时间随机取（10秒内）</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">@Component</div><div class="line">public class Task &#123;</div><div class="line">    public static Random random =new Random();</div><div class="line">    public void doTaskOne() throws Exception &#123;</div><div class="line">        System.out.println(&quot;开始做任务一&quot;);</div><div class="line">        long start = System.currentTimeMillis();</div><div class="line">        Thread.sleep(random.nextInt(10000));</div><div class="line">        long end = System.currentTimeMillis();</div><div class="line">        System.out.println(&quot;完成任务一，耗时：&quot; + (end - start) + &quot;毫秒&quot;);</div><div class="line">    &#125;</div><div class="line">    public void doTaskTwo() throws Exception &#123;</div><div class="line">        System.out.println(&quot;开始做任务二&quot;);</div><div class="line">        long start = System.currentTimeMillis();</div><div class="line">        Thread.sleep(random.nextInt(10000));</div><div class="line">        long end = System.currentTimeMillis();</div><div class="line">        System.out.println(&quot;完成任务二，耗时：&quot; + (end - start) + &quot;毫秒&quot;);</div><div class="line">    &#125;</div><div class="line">    public void doTaskThree() throws Exception &#123;</div><div class="line">        System.out.println(&quot;开始做任务三&quot;);</div><div class="line">        long start = System.currentTimeMillis();</div><div class="line">        Thread.sleep(random.nextInt(10000));</div><div class="line">        long end = System.currentTimeMillis();</div><div class="line">        System.out.println(&quot;完成任务三，耗时：&quot; + (end - start) + &quot;毫秒&quot;);</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ul>
<li>在单元测试用例中，注入Task对象，并在测试用例中执行doTaskOne、doTaskTwo、doTaskThree三个函数</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">@RunWith(SpringJUnit4ClassRunner.class)</div><div class="line">@SpringApplicationConfiguration(classes = Application.class)</div><div class="line">public class ApplicationTests &#123;</div><div class="line">	@Autowired</div><div class="line">	private Task task;</div><div class="line">	@Test</div><div class="line">	public void test() throws Exception &#123;</div><div class="line">		task.doTaskOne();</div><div class="line">		task.doTaskTwo();</div><div class="line">		task.doTaskThree();</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ul>
<li>执行单元测试，可以看到类似如下输出：</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">开始做任务一</div><div class="line">完成任务一，耗时：4256毫秒</div><div class="line">开始做任务二</div><div class="line">完成任务二，耗时：4957毫秒</div><div class="line">开始做任务三</div><div class="line">完成任务三，耗时：7173毫秒</div></pre></td></tr></table></figure>
<p>任务一、任务二、任务三顺序的执行完了，换言之doTaskOne、doTaskTwo、doTaskThree三个函数顺序的执行完成。</p>
<h3 id="异步调用"><a href="#异步调用" class="headerlink" title="异步调用"></a>异步调用</h3><p>上述的同步调用虽然顺利的执行完了三个任务，但是可以看到执行时间比较长，若这三个任务本身之间不存在依赖关系，可以并发执行的话，同步调用在执行效率方面就比较差，可以考虑通过异步调用的方式来并发执行。</p>
<p>在Spring Boot中，我们只需要通过使用@Async注解就能简单的将原来的同步函数变为异步函数，Task类改在为如下模式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">@Component</div><div class="line">public class Task &#123;</div><div class="line">    @Async</div><div class="line">    public void doTaskOne() throws Exception &#123;</div><div class="line">        // 同上内容，省略</div><div class="line">    &#125;</div><div class="line">    @Async</div><div class="line">    public void doTaskTwo() throws Exception &#123;</div><div class="line">        // 同上内容，省略</div><div class="line">    &#125;</div><div class="line">    @Async</div><div class="line">    public void doTaskThree() throws Exception &#123;</div><div class="line">        // 同上内容，省略</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>为了让@Async注解能够生效，还需要在Spring Boot的主程序中配置@EnableAsync，如下所示：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">@SpringBootApplication</div><div class="line">@EnableAsync</div><div class="line">public class Application &#123;</div><div class="line">	public static void main(String[] args) &#123;</div><div class="line">		SpringApplication.run(Application.class, args);</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<ul>
<li><p>此时可以反复执行单元测试，您可能会遇到各种不同的结果，比如：</p>
<p>  没有任何任务相关的输出<br>  有部分任务相关的输出<br>  乱序的任务相关的输出<br>原因是目前doTaskOne、doTaskTwo、doTaskThree三个函数的时候已经是异步执行了。主程序在异步调用之后，主程序并不会理会这三个函数是否执行完成了，由于没有其他需要执行的内容，所以程序就自动结束了，导致了不完整或是没有输出任务相关内容的情况。</p>
</li>
</ul>
<h4 id="注：-Async所修饰的函数不要定义为static类型，这样异步调用不会生效"><a href="#注：-Async所修饰的函数不要定义为static类型，这样异步调用不会生效" class="headerlink" title="注： @Async所修饰的函数不要定义为static类型，这样异步调用不会生效"></a>注： @Async所修饰的函数不要定义为static类型，这样异步调用不会生效</h4><h3 id="异步回调"><a href="#异步回调" class="headerlink" title="异步回调"></a>异步回调</h3><p>为了让doTaskOne、doTaskTwo、doTaskThree能正常结束，假设我们需要统计一下三个任务并发执行共耗时多少，这就需要等到上述三个函数都完成调动之后记录时间，并计算结果。</p>
<p>那么我们如何判断上述三个异步调用是否已经执行完成呢？我们需要使用Future<t>来返回异步调用的结果，就像如下方式改造doTaskOne函数：</t></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">@Async</div><div class="line">public Future&lt;String&gt; doTaskOne() throws Exception &#123;</div><div class="line">    System.out.println(&quot;开始做任务一&quot;);</div><div class="line">    long start = System.currentTimeMillis();</div><div class="line">    Thread.sleep(random.nextInt(10000));</div><div class="line">    long end = System.currentTimeMillis();</div><div class="line">    System.out.println(&quot;完成任务一，耗时：&quot; + (end - start) + &quot;毫秒&quot;);</div><div class="line">    return new AsyncResult&lt;&gt;(&quot;任务一完成&quot;);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>按照如上方式改造一下其他两个异步函数之后，下面我们改造一下测试用例，让测试在等待完成三个异步调用之后来做一些其他事情。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line">@Test</div><div class="line">public void test() throws Exception &#123;</div><div class="line">	long start = System.currentTimeMillis();</div><div class="line">	Future&lt;String&gt; task1 = task.doTaskOne();</div><div class="line">	Future&lt;String&gt; task2 = task.doTaskTwo();</div><div class="line">	Future&lt;String&gt; task3 = task.doTaskThree();</div><div class="line">	while(true) &#123;</div><div class="line">		if(task1.isDone() &amp;&amp; task2.isDone() &amp;&amp; task3.isDone()) &#123;</div><div class="line">			// 三个任务都调用完成，退出循环等待</div><div class="line">			break;</div><div class="line">		&#125;</div><div class="line">		Thread.sleep(1000);</div><div class="line">	&#125;</div><div class="line">	long end = System.currentTimeMillis();</div><div class="line">	System.out.println(&quot;任务全部完成，总耗时：&quot; + (end - start) + &quot;毫秒&quot;);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>看看我们做了哪些改变：</p>
<ul>
<li>在测试用例一开始记录开始时间</li>
<li>在调用三个异步函数的时候，返回Future<string>类型的结果对象</string></li>
<li>在调用完三个异步函数之后，开启一个循环，根据返回的Future<string>对象来判断三个异步函数是否都结束了。若都结束，就结束循环；若没有都结束，就等1秒后再判断。</string></li>
<li>跳出循环之后，根据结束时间 - 开始时间，计算出三个任务并发执行的总耗时。<br>执行一下上述的单元测试，可以看到如下结果：</li>
</ul>
<p>执行一下上述的单元测试，可以看到如下结果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">开始做任务一</div><div class="line">开始做任务二</div><div class="line">开始做任务三</div><div class="line">完成任务三，耗时：37毫秒</div><div class="line">完成任务二，耗时：3661毫秒</div><div class="line">完成任务一，耗时：7149毫秒</div><div class="line">任务全部完成，总耗时：8025毫秒</div></pre></td></tr></table></figure>
        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2017/04/27/Spring Boot中使用@Async实现异步调用/" data-id="cizk115bc0004jj8z2mcanbx4" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2017/04/27/Spring Boot中使用@Async实现异步调用/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2017/04/27/Spring Boot中使用@Async实现异步调用/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-线程数究竟设多少合理" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2017/01/28/线程数究竟设多少合理/">线程数究竟设多少合理</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2017/01/28/线程数究竟设多少合理/">
            <time datetime="2017-01-27T16:00:00.000Z" itemprop="datePublished">2017-01-28</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/服务器/">服务器</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/服务器/">服务器</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>分享一篇，关于线程的经典文章。</p>
</blockquote>
<h3 id="一、需求缘起"><a href="#一、需求缘起" class="headerlink" title="一、需求缘起"></a>一、需求缘起</h3><p>Web-Server通常有个配置，最大工作线程数，后端服务一般也有个配置，工作线程池的线程数量，这个线程数的配置不同的业务架构师有不同的经验值，有些业务设置为CPU核数的2倍，有些业务设置为CPU核数的8倍，有些业务设置为CPU核数的32倍。<br><code>“工作线程数”的设置依据是什么，到底设置为多少能够最大化CPU性能，</code>是本文要讨论的问题。</p>
<h3 id="二、一些共性认知"><a href="#二、一些共性认知" class="headerlink" title="二、一些共性认知"></a>二、一些共性认知</h3><p>在进行进一步深入讨论之前，先以提问的方式就一些共性认知达成一致。</p>
<p><strong>提问：工作线程数是不是设置的越大越好？</strong><br>回答：肯定不是的</p>
<p>1）一来服务器CPU核数有限，同时并发的线程数是有限的，1核CPU设置10000个工作线程没有意义</p>
<p>2）线程切换是有开销的，如果线程切换过于频繁，反而会使性能降低</p>
<p><strong>提问：调用sleep()函数的时候，线程是否一直占用CPU？</strong></p>
<p><em>回答：不占用</em>，等待时会把CPU让出来，给其他需要CPU资源的线程使用</p>
<p>不止调用sleep()函数，在进行一些阻塞调用，例如网络编程中的阻塞accept()【等待客户端连接】和阻塞recv()【等待下游回包】也不占用CPU资源</p>
<p><strong>提问：如果CPU是单核，设置多线程有意义么，能提高并发性能么？</strong></p>
<p>回答：即使是单核，使用多线程也是有意义的<br>1）多线程编码可以让我们的服务/代码更加清晰，有些IO线程收发包，有些Worker线程进行任务处理，有些Timeout线程进行超时检测</p>
<p>2）如果有一个任务一直占用CPU资源在进行计算，那么此时增加线程并不能增加并发，例如这样的一个代码<br> while(1){ i++; }</p>
<p>该代码一直不停的占用CPU资源进行计算，会使CPU占用率达到100%</p>
<p>3）通常来说，Worker线程一般不会一直占用CPU进行计算，此时即使CPU是单核，增加Worker线程也能够提高并发，因为这个线程在休息的时候，其他的线程可以继续工作</p>
<h3 id="三、常见服务线程模型"><a href="#三、常见服务线程模型" class="headerlink" title="三、常见服务线程模型"></a>三、常见服务线程模型</h3><p>了解常见的服务线程模型，有助于理解服务并发的原理，一般来说互联网常见的服务线程模型有如下两种</p>
<p><strong>IO线程与工作线程通过队列解耦类模型</strong></p>
<p><img src="http://mmbiz.qpic.cn/mmbiz/YrezxckhYOxxdwicwqAoloPIfAMycKW160iciaY0RV9GHHLbOoMyEhj4kAicViaSMZQYxybjzFFIQfSmbRd3oTpQuIA/640" alt=""></p>
<p>如上图，大部分Web-Server与服务框架都是使用这样的一种“IO线程与Worker线程通过队列解耦”类线程模型：</p>
<p>1）<strong>有少数几个IO线程</strong>监听上游发过来的请求，并进行收发包（生产者）</p>
<p>2）<strong>有一个或者多个任务队列</strong>，作为IO线程与Worker线程异步解耦的数据传输通道（临界资源）</p>
<p>3）<strong>有多个工作线程</strong>执行正真的任务（消费者）</p>
<p>这个线程模型应用很广，符合大部分场景，这个线程模型的特点是，工作线程内部是同步阻塞执行任务的（回想一下tomcat线程中是怎么执行Java程序的，dubbo工作线程中是怎么执行任务的），因此可以通过增加Worker线程数来增加并发能力，今天要讨论的重点是“该模型Worker线程数设置为多少能达到最大的并发”。</p>
<p><strong>纯异步线程模型</strong><br>任何地方都没有阻塞，这种线程模型只需要设置很少的线程数就能够做到很高的吞吐量，Lighttpd有一种单进程单线程模式，并发处理能力很强，就是使用的的这种模型。该模型的缺点是：</p>
<p>1）如果使用单线程模式，难以利用多CPU多核的优势</p>
<p>2）程序员更习惯写同步代码，callback的方式对代码的可读性有冲击，对程序员的要求也更高</p>
<p>3）框架更复杂，往往需要server端收发组件，server端队列，client端收发组件，client端队列，上下文管理组件，有限状态机组件，超时管理组件的支持<br>however，这个模型不是今天讨论的重点。</p>
<h4 id="四、工作线程的工作模式"><a href="#四、工作线程的工作模式" class="headerlink" title="四、工作线程的工作模式"></a>四、工作线程的工作模式</h4><p>了解工作线程的工作模式，对量化分析线程数的设置非常有帮助：</p>
<p><img src="http://mmbiz.qpic.cn/mmbiz/YrezxckhYOxxdwicwqAoloPIfAMycKW16qTYL2nyXku8PkxicFEuJSQCFmwZtZOoOeTicjx4lBdp2TjvRItJInpNQ/640" alt=""></p>
<p>上图是一个典型的工作线程的处理过程，从开始处理start到结束处理end，该任务的处理共有7个步骤：</p>
<p>1）从工作队列里拿出任务，进行一些本地初始化计算，例如http协议分析、参数解析、参数校验等</p>
<p>2）访问<strong>cache</strong>拿一些数据</p>
<p>3）拿到cache里的数据后，再进行一些本地计算，这些计算和业务逻辑相关</p>
<p>4）通过<strong>RPC</strong>调用下游<strong>service</strong>再拿一些数据，或者让下游service去处理一些相关的任务</p>
<p>5）RPC调用结束后，再进行一些本地计算，怎么计算和业务逻辑相关</p>
<p>6）访问<strong>DB</strong>进行一些数据操作</p>
<p>7）操作完数据库之后做一些收尾工作，同样这些收尾工作也是本地计算，和业务逻辑相关</p>
<p>分析整个处理的时间轴，会发现：</p>
<p>1）其中1，3，5，7步骤中【上图中粉色时间轴】，线程进行本地业务逻辑计算时需要<strong>占用CPU</strong></p>
<p>2）而2，4，6步骤中【上图中橙色时间轴】，访问cache、service、DB过程中线程处于一个等待结果的状态，<strong>不需要占用CPU</strong>，进一步的分解，这个“等待结果”的时间共分为三部分：</p>
<ul>
<li><p>2.1）请求在网络上传输到下游的cache、service、DB</p>
</li>
<li><p>2.2）下游cache、service、DB进行任务处理</p>
</li>
<li><p>2.3）cache、service、DB将报文在网络上传回工作线程</p>
</li>
</ul>
<h3 id="五、量化分析并合理设置工作线程数"><a href="#五、量化分析并合理设置工作线程数" class="headerlink" title="五、量化分析并合理设置工作线程数"></a>五、量化分析并合理设置工作线程数</h3><p>最后一起来回答工作线程数设置为多少合理的问题。</p>
<p>通过上面的分析，Worker线程在执行的过程中，<font color="croci">有一部计算时间需要占用CPU，另一部分等待时间不需要占用CPU，</font>通过量化分析，例如打日志进行统计，可以统计出整个Worker线程执行过程中这两部分时间的比例，例如：</p>
<p>1）时间轴1，3，5，7【上图中粉色时间轴】的计算执行时间是100ms</p>
<p>2）时间轴2，4，6【上图中橙色时间轴】的等待时间也是100ms</p>
<p>得到的结果是，这个线程计算和等待的时间是1：1，即有50%的时间在计算（占用CPU），50%的时间在等待（不占用CPU）：</p>
<p>1）假设此时是<strong>单核</strong>，<font color="croci">则设置为2个工作线程就可以把CPU充分利用起来，让CPU跑到100%</font></p>
<p>2）假设此时是<strong>N核</strong>，<font color="croci">则设置为2N个工作现场就可以把CPU充分利用起来，让CPU跑到N*100%</font></p>
<p>结论：<br>N核服务器，通过执行业务的单线程分析出本地计算时间为x，等待时间为y，则工作线程数（线程池线程数）设置为 N*(x+y)/x，能让CPU的利用率最大化。</p>
<p>经验：<br>一般来说，非CPU密集型的业务（加解密、压缩解压缩、搜索排序等业务是CPU密集型的业务），瓶颈都在后端数据库，本地CPU计算的时间很少，所以设置几十或者几百个工作线程也都是可能的。</p>
<h3 id="六、结论"><a href="#六、结论" class="headerlink" title="六、结论"></a>六、结论</h3><font color="croci"><b><br>N核服务器，通过执行业务的单线程分析出本地计算时间为x，等待时间为y，<br>则工作线程数（线程池线程数）<br>设置为 <strong>N*(x+y)/x</strong>，<br>能让CPU的利用率最大化。</b></font>

<blockquote>
<p>开源中国<a href="http://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&amp;mid=404369373&amp;idx=1&amp;sn=cab2ac9ec0edf92e744a2329662b16cd&amp;scene=21#wechat_redirect" target="_blank" rel="external">原文</a></p>
</blockquote>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2017/01/28/线程数究竟设多少合理/" data-id="cizk115gr001yjj8z05mvquzm" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2017/01/28/线程数究竟设多少合理/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2017/01/28/线程数究竟设多少合理/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-浅谈分布式与集群(未完待续)" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2017/01/27/浅谈分布式与集群(未完待续)/">浅谈分布式与集群(未完待续)</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2017/01/27/浅谈分布式与集群(未完待续)/">
            <time datetime="2017-01-26T16:00:00.000Z" itemprop="datePublished">2017-01-27</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/系统架构/">系统架构</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/分布式与集群/">分布式与集群</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>作者：<a href="https://lxchinesszz.github.io/" target="_blank" rel="external">@lxchinesszz</a><br>本文为作者原创，转载请注明出处</p>
<p>小编最近在做微服务架构的工程，工程是由之前公司的人搭建起来的，说直白就是理论架构，一个业务拆分多个子任务模块，部署在不同的服务器上，通过http协议进行通信，之所以这样其中主要原因是因为，项目开发中用到了不同的语言，对于大多数供销商使用node开发，对于支付使用java开发。在业余时间，小编我是一个喜欢新鲜事物，最近在研究Spring Cloud项目，项目中涉及到了服务的注册，这之间的知识，如果不理解，分布式和集群的区别，很难去学习，在博客上看了很多文章，虽有启发，但是总觉得不是自己总结的，很难吃透，于是一个深夜，趁着失眠，在手机上把内心所想写了，写来，在此总结。本文只做理论上说明，后面会面向单个技术更新博客。</p>
</blockquote>
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>​    作为开发人员，充满了对前辈们的敬仰之情，正是他们的当年的拼命的为了心中的那份对技术单纯的执着，使如今的我们站在了巨人的肩膀上，开发项目，减轻了工作的负担，再次发自内心的感谢。</p>
<p>这些技术就像武功秘籍一样，深深的诱惑这我们，仿佛拿到他们就可以纵横天下。</p>
<ul>
<li>[ ] <code>分布式</code></li>
<li>[ ] <code>集群</code></li>
<li>[ ] <code>机器学习</code></li>
<li>[ ] <code>大数据</code></li>
</ul>
<h4 id="分布式"><a href="#分布式" class="headerlink" title="分布式"></a>分布式</h4><p>所谓的分布式就是并行计算，一个任务一台服务器要10小时计算，在不购买超级服务器的情况下，如何解决这个问题呢，答案就是分布式计算。用小型机群通过技术组成一个超级计算机，就是把这个任务分成十个子任务，每个子任务一个小时，那么等于十台小型机，一个小时就可以完成。</p>
<blockquote>
<p>分布式:不同的业务模块部署在不同的服务器上或者同一个业务模块分拆多个子业务，部署在不同的服务器上，解决高并发的问题</p>
</blockquote>
<hr>
<h4 id="集群"><a href="#集群" class="headerlink" title="集群"></a>集群</h4><p>什么是集群，集群区别于分布式，分布式是一种思想，集群就是一种物理体现。当十个子任务同时到达，如何在一个小时处理完成呢，用十台服务器处理，一台服务器处理一个子任务，也是一个小时就可以完成这十个任务。</p>
<blockquote>
<p>集群:同一个业务部署在多台机器上，提高系统可用性</p>
</blockquote>
<h6 id="两个优点"><a href="#两个优点" class="headerlink" title="两个优点"></a>两个优点</h6><ul>
<li><p>高可用性</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">集群特点，稳定，一台服务挂了，还有其他服务在运行，因为每台服务器都是执行独立的任务。</div></pre></td></tr></table></figure>
</li>
<li><p>可扩展性</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">集群的性能不限于单一的服务实体，新的服务实体可以动态地加入到集群，从而增强集群的性能</div><div class="line"></div><div class="line">eg:</div><div class="line">	当业务量，访问量增大，服务器暴增，就可以扩展集群。</div></pre></td></tr></table></figure>
</li>
</ul>
<h6 id="两大能力"><a href="#两大能力" class="headerlink" title="两大能力"></a>两大能力</h6><ul>
<li><p>负载均衡</p>
<p>​    负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。负载均衡是集群的一项关键技术，通过把请求分发给不同的服务器，从而获得高可用性和较好的性能。常见的就是nginx，我经历的两个公司都有使用，这个是基础配置。</p>
<p><img src="http://www.kuqin.com/upimg/allimg/080418/1513150.gif" alt="图一"></p>
</li>
</ul>
<p>  ​</p>
<blockquote>
<p>推荐文章</p>
</blockquote>
<p>  <a href="http://www.jb51.net/article/79216.htm" target="_blank" rel="external">nginx</a></p>
<p>  <a href="http://www.jianshu.com/p/db963e14df9a" target="_blank" rel="external">Spring Cloud系列五 之 服务网关</a></p>
<p>  <a href="http://www.jianshu.com/p/f93ab5ff4241" target="_blank" rel="external">Spring Cloud系列二 之 Ribbon负载均衡</a></p>
<ul>
<li><p>错误恢复</p>
<p>​    由于某种原因，执行某个任务的资源出现故障，另一服务实体中执行同一任务的资源接着完成任务。这种由于一个实体中的资源不能工作，另一个实体中的资源透明的继续完成任务的过程叫错误恢复。负载均衡和错误恢复都要求各服务实体中有执行同一任务的资源存在，而且对于同一任务的各个资源来说，执行任务所需的信息视图（信息上下文）必须是一样的。</p>
<p><img src="http://www.kuqin.com/upimg/allimg/080418/1513151.gif" alt=""></p>
<p>​</p>
<p>[  注释  ] : 客户端的在请求失败后，被转发到其他服务中处理</p>
</li>
</ul>
<h6 id="两大技术"><a href="#两大技术" class="headerlink" title="两大技术"></a>两大技术</h6><ul>
<li><p>集群地址</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">集群由多个服务实体组成，集群客户端通过访问集群的集群地址获取集群内部各服务实体的功能。具有单一集群地址（也叫单一影像）是集群的一个基 本特征。维护集群地址的设置被称为负载均衡器。负载均衡器内部负责管理各个服务实体的加入和退出，外部负责集群地址向内部服务实体地址的转换。有的负载均 衡器实现真正的负载均衡算法，有的只支持任务的转换。只实现任务转换的负载均衡器适用于支持ACTIVE-STANDBY的集群环境，在那里，集群中只有 一个服务实体工作，当正在工作的服务实体发生故障时，负载均衡器把后来的任务转向另外一个服务实体。</div></pre></td></tr></table></figure>
<p>​</p>
</li>
<li><p>内部通信</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">为了能协同工作、实现负载均衡和错误恢复，集群各实体间必须时常通信，比如负载均衡器对服务实体心跳测试信息、服务实体间任务执行上下文信息的通信。</div><div class="line">具有同一个集群地址使得客户端能访问集群提供的计算服务，一个集群地址下隐藏了各个服务实体的内部地址，使得客户要求的计算服务能在各个服务实体之间分布。内部通信是集群能正常运转的基础，它使得集群具有均衡负载和错误恢复的能力。</div></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="小故事"><a href="#小故事" class="headerlink" title="小故事"></a>小故事</h3><blockquote>
<p>小饭店原来只有一个厨师，切菜洗菜备料炒菜全干。后来客人多了，厨房一个厨师忙不过来，又请了个厨师，两个厨师都能炒一样的菜，这两个厨师的关系是集群。为了让厨师专心炒菜，把菜做到极致，又请了个配菜师负责切菜，备菜，备料，厨师和配菜师的关系是分布式，一个配菜师也忙不过来了，又请了个配菜师，两个配菜师关系是集群</p>
</blockquote>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>再简单的说一点，就是同一个业务按分为子任务运行在不同主机上叫分布式，</p>
<p>同一个业务运行在不同主机上叫集群，两者区别就是业务是否拆分为子任务。是否并行计算。</p>
<p>分布式就不可以，因为是并行计算，虽然提高了计算能力，但是如果一台挂了，那么就会影响这个任务的正常进行。</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2017/01/27/浅谈分布式与集群(未完待续)/" data-id="cizk115gj001vjj8zh7svojoo" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2017/01/27/浅谈分布式与集群(未完待续)/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2017/01/27/浅谈分布式与集群(未完待续)/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud系列五 之 服务网关" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2017/01/11/Spring Cloud系列五 之 服务网关/">Spring Cloud系列五 之 服务网关</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2017/01/11/Spring Cloud系列五 之 服务网关/">
            <time datetime="2017-01-10T16:00:00.000Z" itemprop="datePublished">2017-01-11</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>本篇文章内容简单，但是没有前面的基础是很难理解的，所以推荐看Spring Cloud系列的其他四篇文章，代码实现简单，主要是利用Netflix中的Zuul组件，但是总结起来没有很长的架构师经验是很难深刻理解的，故本文总结内容翻译自程序猿DD Spring Cloud系列博文，所有内容本人都已经测试没有问题，再次非常感谢程序猿DD，的优秀博文分享。本篇文章和前面配置信息Server一样的风格，从提出问题开始，来带领大家一步一步解决问题，解决问题的过程成大家共学习，共成长希望对微服务架构感兴趣的童鞋，有所指引。</p>
</blockquote>
<p>通过之前翻译Spring Cloud组件的介绍，已经能够完成一个简单的微服务架构，大家脑子里都有一个大致的概念。这里通过一个图 描述一下。<br><img src="http://upload-images.jianshu.io/upload_images/4279695-1b4152ed420e9e72.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="架构图"></p>
<p>Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现；而服务间通过Ribbon或Feign实现服务的消费以及均衡负载；通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。为了使得服务集群更为健壮，使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。</p>
<p>在该架构中，我们的服务集群包含：内部服务Service A和Service B，他们都会注册与订阅服务至Eureka Server，而Open Service是一个对外的服务，通过均衡负载公开至服务调用方。本文我们把焦点聚集在对外服务这块，这样的实现是否合理，或者是否有更好的实现方式呢？</p>
<h5 id="先来说说这样架构需要做的一些事儿以及存在的不足："><a href="#先来说说这样架构需要做的一些事儿以及存在的不足：" class="headerlink" title="先来说说这样架构需要做的一些事儿以及存在的不足："></a>先来说说这样架构需要做的一些事儿以及存在的不足：</h5><ul>
<li>首先，破坏了服务无状态特点。为了保证对外服务的安全性，我们需要实现对服务访问的权限控制，而开放服务的权限控制机制将会贯穿并污染整个开放服务的业务逻辑，这会带来的最直接问题是，破坏了服务集群中REST API无状态的特点。从具体开发和测试的角度来说，在工作中除了要考虑实际的业务逻辑之外，还需要额外可续对接口访问的控制处理。</li>
<li>其次，无法直接复用既有接口。当我们需要对一个即有的集群内访问接口，实现外部服务访问时，我们不得不通过在原有接口上增加校验逻辑，或增加一个代理调用来实现权限控制，无法直接复用原有的接口。</li>
</ul>
<h5 id="下面进入本文的正题：服务网关！"><a href="#下面进入本文的正题：服务网关！" class="headerlink" title="下面进入本文的正题：服务网关！"></a>下面进入本文的正题：服务网关！</h5><p>为了解决上面这些问题，我们需要将权限控制这样的东西从我们的服务单元中抽离出去，而最适合这些逻辑的地方就是处于对外访问最前端的地方，我们需要一个更强大一些的均衡负载器，它就是本文将来介绍的：服务网关。</p>
<p>服务网关是微服务架构中一个不可或缺的部分。通过服务网关统一向外系统提供REST API的过程中，除了具备服务路由、均衡负载功能之外，它还具备了权限控制等功能。Spring Cloud Netflix中的Zuul就担任了这样的一个角色，为微服务架构提供了前门保护的作用，同时将权限控制这些较重的非业务逻辑内容迁移到服务路由层面，使得服务集群主体能够具备更高的可复用性和可测试性。</p>
<h2 id="问题汇总"><a href="#问题汇总" class="headerlink" title="问题汇总"></a>问题汇总</h2><ul>
<li>1.如何配置路由服务器</li>
<li><p>2.Zuul服务路由组件两种url映射关系配置</p>
<ul>
<li>2.1 url配置          <code>zuul.routes.api-a-url.url</code></li>
<li>2.2 serviceId配置    <code>zuul.routes.api-b.serviceId</code></li>
</ul>
</li>
<li>3.如何对路由服务器进行安全过滤措施</li>
<li>4.项目演示</li>
</ul>
<h3 id="问题1：如何配置路由服务器"><a href="#问题1：如何配置路由服务器" class="headerlink" title="问题1：如何配置路由服务器"></a>问题1：如何配置路由服务器</h3><p>引入依赖spring-cloud-starter-zuul、spring-cloud-starter-eureka，如果不是通过指定serviceId的方式，eureka依赖不需要，但是为了对服务集群细节的透明性，还是用serviceId来避免直接引用url的方式吧。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">&lt;dependency&gt;</div><div class="line">    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</div><div class="line">    &lt;artifactId&gt;spring-cloud-starter-zuul&lt;/artifactId&gt;</div><div class="line">&lt;/dependency&gt;</div><div class="line">&lt;dependency&gt;</div><div class="line">    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</div><div class="line">    &lt;artifactId&gt;spring-cloud-starter-eureka&lt;/artifactId&gt;</div><div class="line">&lt;/dependency&gt;</div></pre></td></tr></table></figure>
<ul>
<li>应用主类使用@EnableZuulProxy注解开启Zuul</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">@EnableZuulProxy</div><div class="line">@SpringCloudApplication</div><div class="line">public class Application &#123;</div><div class="line">	public static void main(String[] args) &#123;</div><div class="line">		new SpringApplicationBuilder(Application.class).web(true).run(args);</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>这里用了@SpringCloudApplication注解，之前没有提过，通过源码我们看到，它整合了@SpringBootApplication、@EnableDiscoveryClient、@EnableCircuitBreaker，主要目的还是简化配置。这几个注解的具体作用这里就不做详细介绍了，之前的文章已经都介绍过。</p>
<ul>
<li>application.properties中配置Zuul应用的基础信息，如：应用名、服务端口等。</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">spring.application.name=api-gateway</div><div class="line">server.port=5555</div></pre></td></tr></table></figure>
<p>==配置完，服务网关就可以启动了，重点来了，问题二==</p>
<h3 id="问题2：Zuul服务路由组件两种url映射关系配置"><a href="#问题2：Zuul服务路由组件两种url映射关系配置" class="headerlink" title="问题2：Zuul服务路由组件两种url映射关系配置"></a>问题2：Zuul服务路由组件两种url映射关系配置</h3><p>完成上面的工作后，Zuul已经可以运行了，但是如何让它为我们的微服务集群服务，还需要我们另行配置，下面详细的介绍一些常用配置内容。</p>
<ul>
<li>服务路由</li>
</ul>
<p>通过服务路由的功能，我们在对外提供服务的时候，只需要通过暴露Zuul中配置的调用地址就可以让调用方统一的来访问我们的服务，而不需要了解具体提供服务的主机信息了。</p>
<p>在Zuul中提供了两种映射方式：</p>
<ul>
<li>2.1通过url直接映射，我们可以如下配置：</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"># routes to url 当url地址是/api-a-url/**，会自动路由到端口2222的服务上</div><div class="line">zuul.routes.api-a-url.path=/api-a-url/**</div><div class="line">zuul.routes.api-a-url.url=http://localhost:2222/</div><div class="line"># routes to url 当url地址是/api-a-url/**，会自动路由到端口2222的服务上</div><div class="line">zuul.routes.api-b-url.path=/api-b-url/**</div><div class="line">zuul.routes.api-b-url.url=http://localhost:2223/</div><div class="line"></div><div class="line"># 其中zuul.routes.&#123;自定义&#125;.url|path</div></pre></td></tr></table></figure>
<ul>
<li>2.2通过ServiceID映射，我们可以如下配置：</li>
</ul>
<p>通过url映射的方式对于Zuul来说，并不是特别友好，Zuul需要知道我们所有为服务的地址，才能完成所有的映射配置。而实际上，我们在实现微服务架构时，服务名与服务实例地址的关系在eureka server中已经存在了，所以只需要将Zuul注册到eureka server上去发现其他服务，我们就可以实现对serviceId的映射。例如，我们可以如下配置：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">#service-A/service-B是注册到服务器上的Service服务名</div><div class="line">zuul.routes.api-a.path=/api-a/**</div><div class="line">zuul.routes.api-a.serviceId=service-A</div><div class="line">zuul.routes.api-b.path=/api-b/**</div><div class="line">zuul.routes.api-b.serviceId=service-B</div><div class="line">eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/</div></pre></td></tr></table></figure>
<p><img src="http://upload-images.jianshu.io/upload_images/4279695-0923d03d83d4beab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p>
<p>尝试通过服务网关来访问service-A和service-B，根据配置的映射关系，分别访问下面的url</p>
<ul>
<li><a href="http://localhost:5555/api-a/add?a=1&amp;b=2：通过serviceId映射访问service-A中的add服务" target="_blank" rel="external">http://localhost:5555/api-a/add?a=1&amp;b=2：通过serviceId映射访问service-A中的add服务</a></li>
<li><a href="http://localhost:5555/api-b/add?a=1&amp;b=2：通过serviceId映射访问service-B中的add服务" target="_blank" rel="external">http://localhost:5555/api-b/add?a=1&amp;b=2：通过serviceId映射访问service-B中的add服务</a></li>
<li><a href="http://localhost:5555/api-a-url/add?a=1&amp;b=2：通过url映射访问service-A中的add服务" target="_blank" rel="external">http://localhost:5555/api-a-url/add?a=1&amp;b=2：通过url映射访问service-A中的add服务</a></li>
</ul>
<p>推荐使用serviceId的映射方式，除了对Zuul维护上更加友好之外，serviceId映射方式还支持了断路器，对于服务故障的情况下，可以有效的防止故障蔓延到服务网关上而影响整个系统的对外服务</p>
<h3 id="问题3：如何对路由服务器进行安全过滤措施"><a href="#问题3：如何对路由服务器进行安全过滤措施" class="headerlink" title="问题3：如何对路由服务器进行安全过滤措施"></a>问题3：如何对路由服务器进行安全过滤措施</h3><ul>
<li>服务过滤</li>
</ul>
<p>在完成了服务路由之后，我们对外开放服务还需要一些安全措施来保护客户端只能访问它应该访问到的资源。所以我们需要利用Zuul的过滤器来实现我们对外服务的安全控制。</p>
<p>在服务网关中定义过滤器只需要继承ZuulFilter抽象类实现其定义的四个抽象函数就可对请求进行拦截与过滤。</p>
<p>比如下面的例子，定义了一个Zuul过滤器，实现了在请求被路由之前检查请求中是否有accessToken参数，若有就进行路由，若没有就拒绝访问，返回401 Unauthorized错误。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line">public class AccessFilter extends ZuulFilter  &#123;</div><div class="line">    private static Logger log = LoggerFactory.getLogger(AccessFilter.class);</div><div class="line">    @Override</div><div class="line">    public String filterType() &#123;</div><div class="line">        return &quot;pre&quot;;</div><div class="line">    &#125;</div><div class="line">    @Override</div><div class="line">    public int filterOrder() &#123;</div><div class="line">        return 0;</div><div class="line">    &#125;</div><div class="line">    @Override</div><div class="line">    public boolean shouldFilter() &#123;</div><div class="line">        return true;</div><div class="line">    &#125;</div><div class="line">    @Override</div><div class="line">    public Object run() &#123;</div><div class="line">        RequestContext ctx = RequestContext.getCurrentContext();</div><div class="line">        HttpServletRequest request = ctx.getRequest();</div><div class="line">        log.info(String.format(&quot;%s request to %s&quot;, request.getMethod(), request.getRequestURL().toString()));</div><div class="line">        Object accessToken = request.getParameter(&quot;accessToken&quot;);</div><div class="line">        if(accessToken == null) &#123;</div><div class="line">            log.warn(&quot;access token is empty&quot;);</div><div class="line">            ctx.setSendZuulResponse(false);</div><div class="line">            ctx.setResponseStatusCode(401);</div><div class="line">            return null;</div><div class="line">        &#125;</div><div class="line">        log.info(&quot;access token ok&quot;);</div><div class="line">        return null;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>自定义过滤器的实现，需要继承ZuulFilter，需要重写实现下面四个方法：</p>
<ul>
<li>filterType：返回一个字符串代表过滤器的类型，在zuul中定义了四种不同生命周期的过滤器类型，具体如下：<ul>
<li>pre：可以在请求被路由之前调用</li>
<li>routing：在路由请求时候被调用</li>
<li>post：在routing和error过滤器之后被调用</li>
<li>error：处理请求时发生错误时被调用</li>
</ul>
</li>
<li>filterOrder：通过int值来定义过滤器的执行顺序</li>
<li>shouldFilter：返回一个boolean类型来判断该过滤器是否要执行，所以通过此函数可实现过滤器的开关。在上例中，我们直接返回true，所以该过滤器总是生效。</li>
<li>run：过滤器的具体逻辑。需要注意，这里我们通过ctx.setSendZuulResponse(false)令zuul过滤该请求，不对其进行路由，然后通过ctx.setResponseStatusCode(401)设置了其返回的错误码，当然我们也可以进一步优化我们的返回，比如，通过ctx.setResponseBody(body)对返回body内容进行编辑等。</li>
</ul>
<p>在实现了自定义过滤器之后，还需要实例化该过滤器才能生效，我们只需要在应用主类中增加如下内容：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">@EnableZuulProxy</div><div class="line">@SpringCloudApplication</div><div class="line">public class Application &#123;</div><div class="line">	public static void main(String[] args) &#123;</div><div class="line">		new SpringApplicationBuilder(Application.class).web(true).run(args);</div><div class="line">	&#125;</div><div class="line">	@Bean</div><div class="line">	public AccessFilter accessFilter() &#123;</div><div class="line">		return new AccessFilter();</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>启动该服务网关后，访问：</p>
<ul>
<li><a href="http://localhost:5555/api-a/add?a=1&amp;b=2：返回401错误" target="_blank" rel="external">http://localhost:5555/api-a/add?a=1&amp;b=2：返回401错误</a></li>
<li><a href="http://localhost:5555/api-a/add?a=1&amp;b=2&amp;accessToken=token：正确路由到server-A，并返回计算内容" target="_blank" rel="external">http://localhost:5555/api-a/add?a=1&amp;b=2&amp;accessToken=token：正确路由到server-A，并返回计算内容</a></li>
</ul>
<p>下面是过滤器的声明周期图<br><img src="http://upload-images.jianshu.io/upload_images/4279695-ae97a701c1bcc936.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p>
<p>最后，总结一下为什么服务网关是微服务架构的重要部分，是我们必须要去做的原因：</p>
<ul>
<li>不仅仅实现了路由功能来屏蔽诸多服务细节，更实现了服务级别、均衡负载的路由。</li>
<li>实现了接口权限校验与微服务业务逻辑的解耦。通过服务网关中的过滤器，在各生命周期中去校验请求的内容，将原本在对外服务层做的校验前移，保证了微服务的无状态性，同时降低了微服务的测试难度，让服务本身更集中关注业务逻辑的处理。</li>
<li>实现了断路器，不会因为具体微服务的故障而导致服务网关的阻塞，依然可以对外服务。</li>
</ul>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2017/01/11/Spring Cloud系列五 之 服务网关/" data-id="cizk115ck000njj8zwk0srido" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2017/01/11/Spring Cloud系列五 之 服务网关/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2017/01/11/Spring Cloud系列五 之 服务网关/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud系列四 之 配置信息Server" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2016/12/21/Spring Cloud系列四 之 配置信息Server/">Spring Cloud系列四 之 配置信息Server</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2016/12/21/Spring Cloud系列四 之 配置信息Server/">
            <time datetime="2016-12-20T16:00:00.000Z" itemprop="datePublished">2016-12-21</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>小伙伴我刚接触的时候，一脸懵逼，心多有很多疑惑。经历了一周断断续续的开发和学习终于有所头目，故分享给大家，希望大家学习路上少走弯路。<br>本篇文章，通过提出问题的形式，在带领大家一步一步解决问题。</p>
</blockquote>
<h3 id="问题一：如何创建配置信息服务器"><a href="#问题一：如何创建配置信息服务器" class="headerlink" title="问题一：如何创建配置信息服务器"></a>问题一：如何创建配置信息服务器</h3><ul>
<li>注意两点<ul>
<li>1.让配置信息服务器默认从本地文件夹中获得配置信息</li>
<li>2.让配置信息服务器从github或者码云中读取配置信息</li>
<li>3.应用启动要引入那些依赖，pom文件是什么样</li>
</ul>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">1：</div><div class="line">#从本地文件夹中读取，默认是src/main/resource</div><div class="line">spring.profiles.active=native</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"> 2：</div><div class="line">#从服务器中读取</div><div class="line"># github服务器中的个人仓库</div><div class="line">spring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringBoot-Learning/</div><div class="line">#从仓库中选择的配置目录</div><div class="line">spring.cloud.config.server.git.searchPaths=Chapter9-1-4/config-repo</div><div class="line">#登录用户名</div><div class="line">spring.cloud.config.server.git.username=username</div><div class="line">#用户密码</div><div class="line">spring.cloud.config.server.git.password=password</div></pre></td></tr></table></figure>
<p>只要引入这个依赖就可以<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</div><div class="line">	&lt;artifactId&gt;spring-cloud-config-server&lt;/artifactId&gt;</div><div class="line">&lt;/dependency&gt;</div></pre></td></tr></table></figure></p>
<ul>
<li>完整POM文件</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div></pre></td><td class="code"><pre><div class="line">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;</div><div class="line">&lt;project xmlns=&quot;http://maven.apache.org/POM/4.0.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</div><div class="line">	xsi:schemaLocation=&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&gt;</div><div class="line">	&lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;</div><div class="line"></div><div class="line">	&lt;groupId&gt;com.didispace&lt;/groupId&gt;</div><div class="line">	&lt;artifactId&gt;config-server&lt;/artifactId&gt;</div><div class="line">	&lt;version&gt;1.0.0&lt;/version&gt;</div><div class="line">	&lt;packaging&gt;jar&lt;/packaging&gt;</div><div class="line"></div><div class="line">	&lt;name&gt;config-server&lt;/name&gt;</div><div class="line">	&lt;description&gt;Spring Cloud project&lt;/description&gt;</div><div class="line"></div><div class="line">	&lt;parent&gt;</div><div class="line">		&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div class="line">		&lt;artifactId&gt;spring-boot-starter-parent&lt;/artifactId&gt;</div><div class="line">		&lt;version&gt;1.3.5.RELEASE&lt;/version&gt;</div><div class="line">		&lt;relativePath/&gt; &lt;!-- lookup parent from repository --&gt;</div><div class="line">	&lt;/parent&gt;</div><div class="line"></div><div class="line">	&lt;properties&gt;</div><div class="line">		&lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;</div><div class="line">		&lt;java.version&gt;1.8&lt;/java.version&gt;</div><div class="line">	&lt;/properties&gt;</div><div class="line"></div><div class="line">	&lt;dependencies&gt;</div><div class="line"></div><div class="line">		&lt;dependency&gt;</div><div class="line">			&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div class="line">			&lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;</div><div class="line">			&lt;scope&gt;test&lt;/scope&gt;</div><div class="line">		&lt;/dependency&gt;</div><div class="line"></div><div class="line">		&lt;dependency&gt;</div><div class="line">			&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</div><div class="line">			&lt;artifactId&gt;spring-cloud-config-server&lt;/artifactId&gt;</div><div class="line">		&lt;/dependency&gt;</div><div class="line"></div><div class="line">	&lt;/dependencies&gt;</div><div class="line"></div><div class="line">	&lt;dependencyManagement&gt;</div><div class="line">		&lt;dependencies&gt;</div><div class="line">			&lt;dependency&gt;</div><div class="line">				&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;</div><div class="line">				&lt;artifactId&gt;spring-cloud-dependencies&lt;/artifactId&gt;</div><div class="line">				&lt;version&gt;Brixton.RELEASE&lt;/version&gt;</div><div class="line">				&lt;type&gt;pom&lt;/type&gt;</div><div class="line">				&lt;scope&gt;import&lt;/scope&gt;</div><div class="line">			&lt;/dependency&gt;</div><div class="line">		&lt;/dependencies&gt;</div><div class="line">	&lt;/dependencyManagement&gt;</div><div class="line">	</div><div class="line">	&lt;build&gt;</div><div class="line">		&lt;plugins&gt;</div><div class="line">			&lt;plugin&gt;</div><div class="line">				&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div class="line">				&lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;</div><div class="line">			&lt;/plugin&gt;</div><div class="line">		&lt;/plugins&gt;</div><div class="line">	&lt;/build&gt;</div><div class="line"></div><div class="line">&lt;/project&gt;</div></pre></td></tr></table></figure>
<h3 id="问题二：其他项目如何读取-配置服务器中的配置"><a href="#问题二：其他项目如何读取-配置服务器中的配置" class="headerlink" title="问题二：其他项目如何读取 配置服务器中的配置"></a>问题二：其他项目如何读取 配置服务器中的配置</h3><ul>
<li>注意不能使用application.properties<blockquote>
<p>上面这些属性必须配置在bootstrap.properties中，config部分内容才能被正确加载。因为config的相关配置会先于application.properties        </p>
<ul>
<li>创建bootstrap.properties配置，来指定config server，例如：</li>
</ul>
</blockquote>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">#读取的问题名</div><div class="line">spring.application.name=didispace</div><div class="line">#读取的文件环境</div><div class="line">spring.cloud.config.profile=dev</div><div class="line">#配置文件所在的分支</div><div class="line">spring.cloud.config.label=master</div><div class="line">#配置服务器地址</div><div class="line">spring.cloud.config.uri=http://localhost:7001/</div><div class="line">#当前项目的启动端口</div><div class="line">server.port=7002</div></pre></td></tr></table></figure>
<h3 id="问题三：重点来了，配置文件如何命名，服务器才能正确读取"><a href="#问题三：重点来了，配置文件如何命名，服务器才能正确读取" class="headerlink" title="问题三：重点来了，配置文件如何命名，服务器才能正确读取"></a>问题三：重点来了，配置文件如何命名，服务器才能正确读取</h3><ul>
<li><p>URL与配置文件的映射关系如下：</p>
<ul>
<li>/{application}/{profile}[/{label}]</li>
<li>/{application}-{profile}.yml</li>
<li>/{label}/{application}-{profile}.yml</li>
<li>/{application}-{profile}.properties</li>
<li>/{label}/{application}-{profile}.properties</li>
</ul>
</li>
</ul>
<h3 id="问题四：如何从配置服务器中-请求获得不同环境的配置信息"><a href="#问题四：如何从配置服务器中-请求获得不同环境的配置信息" class="headerlink" title="问题四：如何从配置服务器中 请求获得不同环境的配置信息"></a>问题四：如何从配置服务器中 请求获得不同环境的配置信息</h3><ul>
<li>我们可以尝试构造不同的url来访问不同的配置内容，比如：要访问config-label-test分支，didispace应用的prod环境，可以通过这个url：<a href="http://localhost:7001/didispace/prod/config-label-test" target="_blank" rel="external">http://localhost:7001/didispace/prod/config-label-test</a></li>
<li><a href="http://localhost:7001/didispace/{profile环境}/{lable分支}" target="_blank" rel="external">http://localhost:7001/didispace/{profile环境}/{lable分支}</a></li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">&#123;</div><div class="line">    &quot;name&quot;: &quot;didispace&quot;,</div><div class="line">    &quot;profiles&quot;: [</div><div class="line">        &quot;test&quot;</div><div class="line">    ],</div><div class="line">    &quot;label&quot;: &quot;master&quot;,</div><div class="line">    &quot;version&quot;: null,</div><div class="line">    &quot;propertySources&quot;: [</div><div class="line">        &#123;</div><div class="line">            &quot;name&quot;: &quot;classpath:/didispace-test.properties&quot;,</div><div class="line">            &quot;source&quot;: &#123;</div><div class="line">                &quot;from&quot;: &quot;local-test&quot;</div><div class="line">            &#125;</div><div class="line">        &#125;,</div><div class="line">        &#123;</div><div class="line">            &quot;name&quot;: &quot;classpath:/didispace.properties&quot;,</div><div class="line">            &quot;source&quot;: &#123;</div><div class="line">                &quot;from&quot;: &quot;local&quot;</div><div class="line">            &#125;</div><div class="line">        &#125;</div><div class="line">    ]</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h3 id="问题五：实时刷新配置"><a href="#问题五：实时刷新配置" class="headerlink" title="问题五：实时刷新配置"></a>问题五：实时刷新配置</h3><ul>
<li>如何实时刷新，修改git仓库中的配置信息,实时更新到应用中</li>
<li><p>然后在配置服务器：<a href="http://localhost:7002/refresh" target="_blank" rel="external">http://localhost:7002/refresh</a></p>
<ul>
<li>refresh接口要引入节点依赖<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">1&lt;dependency&gt;</div><div class="line">2   &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;</div><div class="line">3   &lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;</div><div class="line">4&lt;/dependency&gt;</div></pre></td></tr></table></figure></li>
</ul>
</li>
</ul>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2016/12/21/Spring Cloud系列四 之 配置信息Server/" data-id="cizk115ca000ljj8zcae39x4e" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2016/12/21/Spring Cloud系列四 之 配置信息Server/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2016/12/21/Spring Cloud系列四 之 配置信息Server/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud系列三 之 Hystrix断路器" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2016/12/16/Spring Cloud系列三 之 Hystrix断路器/">Spring Cloud系列三 之 Hystrix断路器</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2016/12/16/Spring Cloud系列三 之 Hystrix断路器/">
            <time datetime="2016-12-15T16:00:00.000Z" itemprop="datePublished">2016-12-16</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <blockquote>
<p>声明本篇文章部分内容参考自 程序猿DD Spring Cloud系列书籍<br><img src="http://img2.imgtn.bdimg.com/it/u=3823523995,2168010791&amp;fm=23&amp;gp=0.jpg" alt=""></p>
<p>断路器模式源于Martin Fowler的Circuit Breaker一文。“断路器”本身是一种开关装置，用于在电路上保护线路过载，当线路中有电器发生短路时，“断路器”能够及时的切断故障电路，防止发生过载、发热、甚至起火等严重后果。</p>
</blockquote>
<p>在分布式架构中，断路器模式的作用就像是生活中家庭用电，一旦发生短路，就立马断电，不让灾难蔓延。</p>
<h3 id="Netflix-Hystrix"><a href="#Netflix-Hystrix" class="headerlink" title="Netflix Hystrix"></a>Netflix Hystrix</h3><p>在Spring Cloud中使用了Hystrix 来实现断路器的功能。Hystrix是Netflix开源的微服务框架套件之一，该框架目标在于通过控制那些访问远程系统、服务和第三方库的节点，从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离，请求缓存和请求打包，以及监控和配置等功能。</p>
<h4 id="在Spring-Cloud中使用Hystrix组件，是非常容易的，只需要两个注解"><a href="#在Spring-Cloud中使用Hystrix组件，是非常容易的，只需要两个注解" class="headerlink" title="在Spring Cloud中使用Hystrix组件，是非常容易的，只需要两个注解"></a>在Spring Cloud中使用Hystrix组件，是非常容易的，只需要两个注解</h4><ul>
<li>准备工作</li>
</ul>
<p>首先启动(eureka-server)服务注册中心，两个Service服务</p>
<ul>
<li>添加Hystrix断路器组件</li>
</ul>
<p>只需要引入Hystrix依赖，在Ribbon负载均衡应用启动类添加@EnableCircuitBreaker</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">@SpringBootApplication</div><div class="line">@EnableDiscoveryClient</div><div class="line">@EnableCircuitBreaker</div><div class="line">public class RibbonApplication &#123;</div><div class="line">	@Bean</div><div class="line">	@LoadBalanced</div><div class="line">	RestTemplate restTemplate() &#123;</div><div class="line">		return new RestTemplate();</div><div class="line">	&#125;</div><div class="line">	public static void main(String[] args) &#123;</div><div class="line">		SpringApplication.run(RibbonApplication.class, args);</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>改造原来的服务消费方式，新增ComputeService类，在使用ribbon消费服务的函数上增加@HystrixCommand注解来指定回调方法。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">@Service</div><div class="line">public class ComputeService &#123;</div><div class="line">    @Autowired</div><div class="line">    RestTemplate restTemplate;</div><div class="line">    @HystrixCommand(fallbackMethod = &quot;addServiceFallback&quot;)//回调方法</div><div class="line">    public String addService() &#123;</div><div class="line">        return restTemplate.getForEntity(&quot;http://COMPUTE-SERVICE/add?a=10&amp;b=20&quot;, String.class).getBody();</div><div class="line">    &#125;</div><div class="line">    public String addServiceFallback() &#123; //回调方法</div><div class="line">        return &quot;error&quot;;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<ul>
<li>验证断路器的回调<ul>
<li>依次启动eureka-server、compute-service、eureka-ribbon工程</li>
<li>访问<a href="http://localhost:1111/可以看到注册中心的状态" target="_blank" rel="external">http://localhost:1111/可以看到注册中心的状态</a></li>
<li>访问<a href="http://localhost:3333/add，页面显示：30" target="_blank" rel="external">http://localhost:3333/add，页面显示：30</a></li>
<li>关闭compute-service服务后再访问<a href="http://localhost:3333/add，" target="_blank" rel="external">http://localhost:3333/add，</a></li>
<li>页面显示：error</li>
<li></li>
</ul>
</li>
</ul>
<blockquote>
<p>本文标题：Dekel Tankel 谈 Cloud Foundry 与 Spring 前景<br>本文地址：<a href="https://www.oschina.net/news/68979/cloudfundry-meetup" target="_blank" rel="external">https://www.oschina.net/news/68979/cloudfundry-meetup</a></p>
</blockquote>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2016/12/16/Spring Cloud系列三 之 Hystrix断路器/" data-id="cizk115c4000fjj8z1ujcve4v" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2016/12/16/Spring Cloud系列三 之 Hystrix断路器/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2016/12/16/Spring Cloud系列三 之 Hystrix断路器/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud系列二 之 Ribbon负载均衡" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2016/12/11/Spring Cloud系列二 之 Ribbon负载均衡/">Spring Cloud系列二 之 Ribbon负载均衡</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2016/12/11/Spring Cloud系列二 之 Ribbon负载均衡/">
            <time datetime="2016-12-10T16:00:00.000Z" itemprop="datePublished">2016-12-11</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <p>balancer：均衡器</p>
<p>如果是自己写一个负载均衡器思路应该是什么？<br>参考nginx，部署多个服务，形成一对多的关系<br>当一个请求发送，通过拦截这个请求，随机或者算法到其中的一个服务上去处理<br>那么，这中间关键的一点就是：拦截</p>
<p>最精简的LB需求：</p>
<ul>
<li>设置添加和读取后端服务器的列表</li>
<li>能从中选择一个服务器去执行<br>代码实现思路就是：<br>读取后端服务，标记一个服务不可用，最主要是选择一个后端服务来提供服务</li>
</ul>
<p>//使用负载均衡加载服务<br>public interface ILoadBalancer {<br>    void addServers(List<server> var1);向负载均衡器中维护的实例列表增加服务实例。<br>    Server chooseServer(Object var1);通过某种策略，从负载均衡器中挑选出一个具体的服务实例。<br>    void markServerDown(Server var1);用来通知和标识负载均衡器中某个具体实例已经停止服务，不然负载均衡器在下一次获取服务实例清单前都会认为服务实例均是正常服务的。<br>    List<server> getServerList(boolean var1);//目的兼容2.1.3以前的。（之后本方法拆分下面两个）<br>    List<server> getReachableServers();获取当前正常服务的实例列表。<br>    List<server> getAllServers();获取所有已知的服务实例列表，包括正常服务和停止服务的实例。<br>}<br>ILoadBalancer：<br>基础实现类 com.netflix.loadbalancer.BaseLoadBalancer<br>扩展功能         DynamicServerListLoadBalancer和ZoneAwareLoadBalancer</server></server></server></server></p>
<p>通过查看BaseLoadBalancer源码发现：</p>
<ul>
<li>里面几个重要的对象</li>
</ul>
<p>1.通过（@LoadBalanced）注解的形式去拦截：RestTemplate的请求</p>
<p>@Autowired<br>RestTemplate restTemplate;<br>/**</p>
<ul>
<li>当网络不稳定的情况下，配置返回信息<br>*</li>
<li>当一个被@LoadBalanced注解修饰的RestTemplate对象向外发起HTTP请求时，</li>
<li>会被LoadBalancerInterceptor类的intercept函数所拦截。</li>
<li>由于我们在使用RestTemplate时候采用了服务名作为host，</li>
<li>所以直接从HttpRequest的URI对象中通过getHost()就可以拿到服务名，</li>
<li>然后调用execute函数去根据服务名来选择实例并发起实际的请求。</li>
<li>@return<br>*/<br>@HystrixCommand(fallbackMethod = “addServiceFallback”)<br>public String addService() {<br> return restTemplate.getForEntity(“<a href="http://COMPUTE-SERVICE/add?a=10&amp;b=20" target="_blank" rel="external">http://COMPUTE-SERVICE/add?a=10&amp;b=20</a>“, String.class).getBody();<br>}<br>public String addServiceFallback() {<br> return “error”;<br>}</li>
</ul>
<p>2.LoadBalancerInterceptor中的intercept会拦截RestTemplate中的请求</p>
<p>public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {<br>    URI originalUri = request.getURI();//获得请求的地址，因为是host是服务名<br>    String serviceName = originalUri.getHost();<br>    return (ClientHttpResponse)this.loadBalancer.execute(serviceName, new LoadBalancerRequest() {<br>        public ClientHttpResponse apply(ServiceInstance instance) throws Exception {<br>            LoadBalancerInterceptor.ServiceRequestWrapper serviceRequest = LoadBalancerInterceptor.this.new ServiceRequestWrapper(request, instance);<br>            return execution.execute(serviceRequest, body);<br>        }<br>    });<br>}<br>3.通过搜索LoadBalancerClient，我们可以发现这是Spring Cloud中定义的一个接口：</p>
<p>public interface LoadBalancerClient {<br>    ServiceInstance choose(String serviceId);  //选择服务实例，根据传入的服务名serviceId，从负载均衡器中挑选一个对应服务的实例。<br>    <t> T execute(String serviceId, LoadBalancerRequest<t> request) throws IOException; //使用从负载均衡器中挑选出的服务实例来执行请求内容。<br>    URI reconstructURI(ServiceInstance instance, URI original);<br>}</t></t></p>
<p>这个接口的具体实现类是RibbonLoadBalancerClient</p>
<p>负载均衡器应用也是SpringBoot普通应用，不过要配置RestTemplate对象<br>@SpringBootApplication<br>@EnableDiscoveryClient<br>@EnableCircuitBreaker<br>public class RibbonApplication {<br>   /**</p>
<pre><code>* @LoadBalanced注解源码的注释中，我们可以知道该注解用来给RestTemplate标记，
* 以使用负载均衡的客户端（LoadBalancerClient）来配置它。
* @return
*/
</code></pre><p>   @Bean<br>   @LoadBalanced<br>   RestTemplate restTemplate() {<br>      return new RestTemplate();<br>   }</p>
<p>   public static void main(String[] args) {<br>      SpringApplication.run(RibbonApplication.class, args);<br>   }</p>
<p>}</p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2016/12/11/Spring Cloud系列二 之 Ribbon负载均衡/" data-id="cizk115c7000hjj8zn5he6m9f" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2016/12/11/Spring Cloud系列二 之 Ribbon负载均衡/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2016/12/11/Spring Cloud系列二 之 Ribbon负载均衡/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud系列一 之 eureka服务注册中心" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2016/11/29/Spring Cloud系列一 之 eureka服务注册中心/">Spring Cloud系列一 之 eureka服务注册中心</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2016/11/29/Spring Cloud系列一 之 eureka服务注册中心/">
            <time datetime="2016-11-28T16:00:00.000Z" itemprop="datePublished">2016-11-29</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <h2 id="服务发现：Eureka客户端"><a href="#服务发现：Eureka客户端" class="headerlink" title="服务发现：Eureka客户端"></a>服务发现：Eureka客户端</h2><blockquote>
<p>服务发现是微服务架构中的一项核心服务。如果没有该服务，我们就只能为每一个服务调用者手工配置可用服务的地址，这不仅繁琐而且非常容易出错。Eureka包括了服务端和客户端两部分。服务端可以做到高可用集群部署，每一个节点可以自动同步，有相同的服务注册信息。</p>
</blockquote>
<p>向Eureka注册服务<br>当客户端向Eureka注册自己时会提供一些元信息，如主机名、端口号、获取健康信息的url和主页等。Eureka通过心跳连接判断服务是否在线，如果心跳检测失败超过指定时间，对应的服务通常就会被移出可用服务列表。<br>译者注：向Eureka Server注册过的服务会每30秒向Server发送一次心跳连接, Server会根据心跳数据更新该服务的健康状态并复制到其他Server中。如果超过90秒没有收到该服务的心跳数据，则Server会将该服务移出列表。</p>
<p>注册项目实际就是一个普通的Spring Boot应用，使用@EnableDiscoveryClient注解后，会自动向Eureka注册中心，变成Rureka服务端实例，</p>
<p>服务注册中心实际也是一个普通SpringBoot应用，使用了@EnableEurekaServer注解后，启动应用，Eureka有一个带UI的主页，注册信息都在/访问<br><img src="http://note.youdao.com/src/WEBRESOURCE99f35b85d334533db63f94645b8897b6" alt=""></p>
<p> Basic Architecture<br><img src="http://note.youdao.com/src/BFEDD654CE864C449BD05AF49194E1D0" alt=""><br>上图简要描述了Eureka的基本架构，由3个角色组成：<br>Eureka Server</p>
<p>提供服务注册和发现</p>
<p>Service Provider</p>
<p>服务提供方<br>将自身服务注册到Eureka，从而使服务消费方能够找到</p>
<p>Service Consumer</p>
<p>服务消费方<br>从Eureka获取注册服务列表，从而能够消费服务</p>
<p>需要注意的是，上图中的3个角色都是逻辑角色。在实际运行中，这几个角色甚至可以是同一个实例，比如在我们项目中，Eureka Server和Service Provider就是同一个JVM进程。</p>
<p>More in depth<br><img src="http://note.youdao.com/src/F144D3BE7F1B4E6D90281132C4DEAC14" alt=""><br>上图更进一步的展示了3个角色之间的交互。<br>Service Provider会向Eureka Server做Register（服务注册）、Renew（服务续约）、Cancel（服务下线）等操作。<br>Eureka Server之间会做注册服务的同步，从而保证状态一致<br>Service Consumer会向Eureka Server获取注册服务列表，并消费服务</p>
<p>实现细节：<br>ApplicationResource类接收Http服务请求，调用PeerAwareInstanceRegistryImpl的register方法</p>
<p>private final PeerAwareInstanceRegistry registry;//实现注册 InstancInfo包含 instancdId、appName、ipAddr、port、securePosrt….<br>@POST<br>@Consumes({“application/json”, “application/xml”})<br>public Response addInstance(InstanceInfo info, @HeaderParam(“x-netflix-discovery-replication”) String isReplication) {<br> logger.debug(“Registering instance {} (replication={})”, info.getId(), isReplication);<br> ….处理失败返回<br> this.registry.register(info, “true”.equals(isReplication));<br> return Response.status(204).build();<br> }<br>PeerAwareInstanceRegistryImpl完成服务注册后，调用replicateToPeers向其它Eureka Server节点（Peer）做状态同步</p>
<p><img src="http://note.youdao.com/src/70FE50FDF79346DE9823AD6E055C94A2" alt=""></p>
<p>Chapter9-1-1 实现简单注册功能</p>
<p>未完待续。。。<br>参考资料：<a href="http://docs.springcloud.cn/user-guide/eureka/" target="_blank" rel="external">http://docs.springcloud.cn/user-guide/eureka/</a><br>参考资料：<a href="http://nobodyiam.com/2016/06/25/dive-into-eureka/（细节实现）" target="_blank" rel="external">http://nobodyiam.com/2016/06/25/dive-into-eureka/（细节实现）</a></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2016/11/29/Spring Cloud系列一 之 eureka服务注册中心/" data-id="cizk115bz000cjj8zr915ck3m" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2016/11/29/Spring Cloud系列一 之 eureka服务注册中心/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2016/11/29/Spring Cloud系列一 之 eureka服务注册中心/">评论</a>
    

        </footer>
    </div>
    
</article>



    <article id="Layout-Spring Cloud初步理解" class="article article-type-Layout" itemscope itemprop="blogPost">
    <div class="article-inner">
        
        
            <header class="article-header">
                
    
        <h1 itemprop="name">
            <a class="article-title" href="/2016/10/11/Spring Cloud初步理解/">Spring Cloud初步理解</a>
        </h1>
    

                
                    <div class="article-meta">
                        
    <div class="article-date">
        <i class="fa fa-calendar"></i>
        <a href="/2016/10/11/Spring Cloud初步理解/">
            <time datetime="2016-10-10T16:00:00.000Z" itemprop="datePublished">2016-10-11</time>
        </a>
    </div>


                        
    <div class="article-category">
    	<i class="fa fa-folder"></i>
        <a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a>
    </div>

                        
    <div class="article-tag">
        <i class="fa fa-tag"></i>
        <a class="tag-link" href="/tags/Spring-Cloud/">Spring Cloud</a>
    </div>

                    </div>
                
            </header>
        
        
        <div class="article-entry" itemprop="articleBody">
        
            
            <hr>
<h3 id="Ribbon实现负载均衡"><a href="#Ribbon实现负载均衡" class="headerlink" title="Ribbon实现负载均衡"></a>Ribbon实现负载均衡</h3><blockquote>
<p>关键字：Feign、Ribbon、eureka、负载均衡</p>
</blockquote>
<ol>
<li><p>大致：步骤，启动eureka服务(注册中心)</p>
<ul>
<li>使用Spring Cloud Netflix中的Eureka实现服务注册中心，以及服务注册发现；</li>
</ul>
</li>
<li><p>将service(port:2222,port:2223)注册到eureka服务中</p>
</li>
<li>使用Ribbon代理去访问service<ul>
<li><font color="red">会实现负载均衡</font></li>
<li>服务间通过Ribbon或Feign实现服务的消费以及均衡负载</li>
</ul>
</li>
<li>通过Spring Cloud Config实现应用多环境的外部化配置及版本管理<ul>
<li>使得服务集群更为健壮，使用Hystrix熔断机制避免微服务架构中个别服务出现异常引起的故障蔓延</li>
</ul>
</li>
</ol>
<blockquote>
<p>引入断路器 Rabbion中引入Hystrix</p>
</blockquote>
<pre><code><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">@Service</div><div class="line">public class ComputeService &#123;</div><div class="line">    @Autowired</div><div class="line">    RestTemplate restTemplate;</div><div class="line">    @HystrixCommand(fallbackMethod = &quot;addServiceFallback&quot;)</div><div class="line">    public String addService() &#123;</div><div class="line">        return restTemplate.getForEntity(&quot;http://COMPUTE-SERVICE/add?a=10&amp;b=20&quot;, String.class).getBody();</div><div class="line">    &#125;</div><div class="line">    public String addServiceFallback() &#123;</div><div class="line">        return &quot;error&quot;;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
</code></pre><p><img src="http://upload-images.jianshu.io/upload_images/4279695-00840cf246604c16.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="架构图"></p>

        
        </div>
        <footer class="article-footer">
            <div class="share-container">



</div>

    <a data-url="http://yoursite.com/2016/10/11/Spring Cloud初步理解/" data-id="cizk115bp000ajj8z7vegqkzg" class="article-share-link"><i class="fa fa-share"></i>分享到</a>
<script>
    (function ($) {
        // Prevent duplicate binding
        if (typeof(__SHARE_BUTTON_BINDED__) === 'undefined' || !__SHARE_BUTTON_BINDED__) {
            __SHARE_BUTTON_BINDED__ = true;
        } else {
            return;
        }
        $('body').on('click', function() {
            $('.article-share-box.on').removeClass('on');
        }).on('click', '.article-share-link', function(e) {
            e.stopPropagation();

            var $this = $(this),
                url = $this.attr('data-url'),
                encodedUrl = encodeURIComponent(url),
                id = 'article-share-box-' + $this.attr('data-id'),
                offset = $this.offset(),
                box;

            if ($('#' + id).length) {
                box = $('#' + id);

                if (box.hasClass('on')){
                    box.removeClass('on');
                    return;
                }
            } else {
                var html = [
                    '<div id="' + id + '" class="article-share-box">',
                        '<input class="article-share-input" value="' + url + '">',
                        '<div class="article-share-links">',
                            '<a href="https://twitter.com/intent/tweet?url=' + encodedUrl + '" class="fa fa-twitter article-share-twitter" target="_blank" title="Twitter"></a>',
                            '<a href="https://www.facebook.com/sharer.php?u=' + encodedUrl + '" class="fa fa-facebook article-share-facebook" target="_blank" title="Facebook"></a>',
                            '<a href="http://pinterest.com/pin/create/button/?url=' + encodedUrl + '" class="fa fa-pinterest article-share-pinterest" target="_blank" title="Pinterest"></a>',
                            '<a href="https://plus.google.com/share?url=' + encodedUrl + '" class="fa fa-google article-share-google" target="_blank" title="Google+"></a>',
                        '</div>',
                    '</div>'
                ].join('');

              box = $(html);

              $('body').append(box);
            }

            $('.article-share-box.on').hide();

            box.css({
                top: offset.top + 25,
                left: offset.left
            }).addClass('on');

        }).on('click', '.article-share-box', function (e) {
            e.stopPropagation();
        }).on('click', '.article-share-box-input', function () {
            $(this).select();
        }).on('click', '.article-share-box-link', function (e) {
            e.preventDefault();
            e.stopPropagation();

            window.open(this.href, 'article-share-box-window-' + Date.now(), 'width=500,height=450');
        });
    })(jQuery);
</script>

            
    
        <a href="http://yoursite.com/2016/10/11/Spring Cloud初步理解/#comments" class="article-comment-link ds-thread-count" data-thread-key="http://yoursite.com/2016/10/11/Spring Cloud初步理解/">评论</a>
    

        </footer>
    </div>
    
</article>



    <nav id="page-nav">
        <span class="page-number current">1</span><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><a class="extend next" rel="next" href="/page/2/">下一页 &raquo;</a>
    </nav>
</section>
            
                <aside id="sidebar">
   
        
    <div class="widget-wrap">
        <h3 class="widget-title">最新文章</h3>
        <div class="widget">
            <ul id="recent-post" class="">
                
                    <li>
                        
                        <div class="item-thumbnail">
                            <a href="/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/" class="thumbnail">
    
    
        <span class="thumbnail-image thumbnail-none"></span>
    
</a>

                        </div>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/服务器/">服务器</a></p>
                            <p class="item-title"><a href="/2017/05/17/CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程/" class="title">CPU-bound(计算密集型) 和IO bound(IO密集型)、进程vs线程</a></p>
                            <p class="item-date"><time datetime="2017-05-16T16:00:00.000Z" itemprop="datePublished">2017-05-17</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-thumbnail">
                            <a href="/2017/04/27/Spring Boot中使用@Async实现异步调用/" class="thumbnail">
    
    
        <span class="thumbnail-image thumbnail-none"></span>
    
</a>

                        </div>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/Spring-Boot实战/">Spring Boot实战</a></p>
                            <p class="item-title"><a href="/2017/04/27/Spring Boot中使用@Async实现异步调用/" class="title">Spring Boot中使用@Async实现异步调用</a></p>
                            <p class="item-date"><time datetime="2017-04-26T16:00:00.000Z" itemprop="datePublished">2017-04-27</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-thumbnail">
                            <a href="/2017/01/28/线程数究竟设多少合理/" class="thumbnail">
    
    
        <span class="thumbnail-image thumbnail-none"></span>
    
</a>

                        </div>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/服务器/">服务器</a></p>
                            <p class="item-title"><a href="/2017/01/28/线程数究竟设多少合理/" class="title">线程数究竟设多少合理</a></p>
                            <p class="item-date"><time datetime="2017-01-27T16:00:00.000Z" itemprop="datePublished">2017-01-28</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-thumbnail">
                            <a href="/2017/01/27/浅谈分布式与集群(未完待续)/" class="thumbnail">
    
    
        <span class="thumbnail-image thumbnail-none"></span>
    
</a>

                        </div>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/系统架构/">系统架构</a></p>
                            <p class="item-title"><a href="/2017/01/27/浅谈分布式与集群(未完待续)/" class="title">浅谈分布式与集群(未完待续)</a></p>
                            <p class="item-date"><time datetime="2017-01-26T16:00:00.000Z" itemprop="datePublished">2017-01-27</time></p>
                        </div>
                    </li>
                
                    <li>
                        
                        <div class="item-thumbnail">
                            <a href="/2017/01/11/Spring Cloud系列五 之 服务网关/" class="thumbnail">
    
    
        <span class="thumbnail-image thumbnail-none"></span>
    
</a>

                        </div>
                        
                        <div class="item-inner">
                            <p class="item-category"><a class="article-category-link" href="/categories/Spring-Cloud/">Spring Cloud</a></p>
                            <p class="item-title"><a href="/2017/01/11/Spring Cloud系列五 之 服务网关/" class="title">Spring Cloud系列五 之 服务网关</a></p>
                            <p class="item-date"><time datetime="2017-01-10T16:00:00.000Z" itemprop="datePublished">2017-01-11</time></p>
                        </div>
                    </li>
                
            </ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">分类</h3>
        <div class="widget">
            <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Java命名规范/">Java命名规范</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Spring-Boot实战/">Spring Boot实战</a><span class="category-list-count">13</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Spring-Cloud/">Spring Cloud</a><span class="category-list-count">6</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/服务器/">服务器</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/服务器搭建/">服务器搭建</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/系统架构/">系统架构</a><span class="category-list-count">1</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">归档</h3>
        <div class="widget">
            <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/05/">五月 2017</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/04/">四月 2017</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/01/">一月 2017</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/12/">十二月 2016</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/11/">十一月 2016</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/10/">十月 2016</a><span class="archive-list-count">1</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/08/">八月 2016</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/07/">七月 2016</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/06/">六月 2016</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/05/">五月 2016</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2016/01/">一月 2016</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2015/01/">一月 2015</a><span class="archive-list-count">1</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签</h3>
        <div class="widget">
            <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Java命名规范/">Java命名规范</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Maven/">Maven</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Boot中使用-Async实现异步调用/">Spring Boot中使用@Async实现异步调用</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Boot注解/">Spring Boot注解</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring-Cloud/">Spring Cloud</a><span class="tag-list-count">6</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot原生定时任务解析/">SpringBoot原生定时任务解析</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot在启动类配置端口号/">SpringBoot在启动类配置端口号</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot拦截器/">SpringBoot拦截器</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/SpringBoot配置视图/">SpringBoot配置视图</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Spring整合Quartz2-1-1/">Spring整合Quartz2.1.1</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/优化方案/">优化方案</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/分布式与集群/">分布式与集群</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/动态读取任务执行/">动态读取任务执行</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/启动环境/">启动环境</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/整合定时任务/">整合定时任务</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/服务器/">服务器</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/服务器搭建/">服务器搭建</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/计算/">计算</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/配置文件加载/">配置文件加载</a><span class="tag-list-count">1</span></li></ul>
        </div>
    </div>

    
        
    <div class="widget-wrap">
        <h3 class="widget-title">标签云</h3>
        <div class="widget tagcloud">
            <a href="/tags/Java命名规范/" style="font-size: 10px;">Java命名规范</a> <a href="/tags/Maven/" style="font-size: 10px;">Maven</a> <a href="/tags/Spring-Boot中使用-Async实现异步调用/" style="font-size: 10px;">Spring Boot中使用@Async实现异步调用</a> <a href="/tags/Spring-Boot注解/" style="font-size: 10px;">Spring Boot注解</a> <a href="/tags/Spring-Cloud/" style="font-size: 20px;">Spring Cloud</a> <a href="/tags/SpringBoot原生定时任务解析/" style="font-size: 10px;">SpringBoot原生定时任务解析</a> <a href="/tags/SpringBoot在启动类配置端口号/" style="font-size: 10px;">SpringBoot在启动类配置端口号</a> <a href="/tags/SpringBoot拦截器/" style="font-size: 10px;">SpringBoot拦截器</a> <a href="/tags/SpringBoot配置视图/" style="font-size: 10px;">SpringBoot配置视图</a> <a href="/tags/Spring整合Quartz2-1-1/" style="font-size: 10px;">Spring整合Quartz2.1.1</a> <a href="/tags/优化方案/" style="font-size: 10px;">优化方案</a> <a href="/tags/分布式与集群/" style="font-size: 10px;">分布式与集群</a> <a href="/tags/动态读取任务执行/" style="font-size: 10px;">动态读取任务执行</a> <a href="/tags/启动环境/" style="font-size: 10px;">启动环境</a> <a href="/tags/整合定时任务/" style="font-size: 10px;">整合定时任务</a> <a href="/tags/服务器/" style="font-size: 10px;">服务器</a> <a href="/tags/服务器搭建/" style="font-size: 15px;">服务器搭建</a> <a href="/tags/计算/" style="font-size: 10px;">计算</a> <a href="/tags/配置文件加载/" style="font-size: 10px;">配置文件加载</a>
        </div>
    </div>

    
        
    <div class="widget-wrap widget-list">
        <h3 class="widget-title">链接</h3>
        <div class="widget">
            <ul>
                
                    <li>
                        <a href="http://www.jianshu.com/u/e210c8fa704f">简书</a>
                    </li>
                
                    <li>
                        <a href="http://blog.csdn.net/message_lx/article/details/56674087">CSDN</a>
                    </li>
                
                    <li>
                        <a href="https://www.zhihu.com/people/chinesszz/activities">知乎</a>
                    </li>
                
                    <li>
                        <a href="https://my.oschina.net/chinesszz/blog">开源中国</a>
                    </li>
                
                    <li>
                        <a href="https://lxchinesszz.github.io/">GITHUB博客</a>
                    </li>
                
            </ul>
        </div>
    </div>


    
    <div id="toTop" class="fa fa-angle-up"></div>
</aside>
            
        </div>
        <footer id="footer">
    <div class="outer">
        <div id="footer-info" class="inner">
            &copy; 2017<br>
            <a href="http://www.jianshu.com/u/e210c8fa704f" target="_blank">简书</a>. by <a href="https://github.com/lxchinesszz">Liuxin</a>
        </div>
    </div>
</footer>
        
    
    <script type="text/javascript">
    var duoshuoQuery = {short_name:'lxchinesszz'};
    (function() {
    var ds = document.createElement('script');
    ds.type = 'text/javascript';ds.async = true;
    ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
    ds.charset = 'UTF-8';
    (document.getElementsByTagName('head')[0]
    || document.getElementsByTagName('body')[0]).appendChild(ds);
    })();
    </script>



    
        <script src="/libs/lightgallery/js/lightgallery.min.js"></script>
        <script src="/libs/lightgallery/js/lg-thumbnail.min.js"></script>
        <script src="/libs/lightgallery/js/lg-pager.min.js"></script>
        <script src="/libs/lightgallery/js/lg-autoplay.min.js"></script>
        <script src="/libs/lightgallery/js/lg-fullscreen.min.js"></script>
        <script src="/libs/lightgallery/js/lg-zoom.min.js"></script>
        <script src="/libs/lightgallery/js/lg-hash.min.js"></script>
        <script src="/libs/lightgallery/js/lg-share.min.js"></script>
        <script src="/libs/lightgallery/js/lg-video.min.js"></script>
    
    
        <script src="/libs/justified-gallery/jquery.justifiedGallery.min.js"></script>
    



<!-- Custom Scripts -->
<script src="/js/main.js"></script>

    </div>
</body>
</html>